#pragma once
#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<cstdlib>
#include<cstring>

#include"log.hpp"

#define LONG 5
class TcpServer{
    private:
        int port;
        int listen_sock;
        static TcpServer* str;
        static pthread_mutex_t lock;
    public:
        static TcpServer* GetServerObj(int _post){
            if(str==nullptr){
                pthread_mutex_lock(&lock);
                if(str==nullptr){
                    str=new TcpServer(_post);
                    str->initiailzer();
                    LOG(INFO,"initiailzer success...");
                    return str;
                }
                pthread_mutex_unlock(&lock);
            }
            return str;
        }
    private:
        TcpServer(int _port):port(_port),listen_sock(-1)
        {}
        void initiailzer()
        {
            Sock();
            Bind();
            Listen();
        }
        void Sock(){
            listen_sock=socket(AF_INET,SOCK_STREAM,0);
            if(listen_sock<0){
                LOG(ERROR,"socket fail...");
                exit(1);
            }
            LOG(INFO,"socket success...");
            int opt=1;
            setsockopt(listen_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
        }
        void Bind(){
            struct sockaddr_in own;
            own.sin_family=AF_INET;
            own.sin_port=htons(port);
            own.sin_addr.s_addr=INADDR_ANY;
            if(bind(listen_sock,(struct sockaddr*)&own,sizeof(own))<0){
                LOG(ERROR,"bind fail...");
                exit(2);
            }
            LOG(INFO,"bindsuccess...");
        }
        void Listen(){
            if(listen(listen_sock,LONG)<0){
                LOG(ERROR,"listen fail...");
                exit(3);
            }
            LOG(INFO,"listen success...");
        }
    public:
        int RenturnSock(){
            int _sock=listen_sock;
            return _sock;
        }
        ~TcpServer(){
            if(listen_sock>=0)
                close(listen_sock);
        }
};
TcpServer* TcpServer::str=nullptr;
pthread_mutex_t TcpServer::lock=PTHREAD_MUTEX_INITIALIZER;